#ifndef USER_PLUGIN_DUMMY
#define USER_PLUGIN_DUMMY
#include <iostream>
#include <string>
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include "../../../libpland/lib/plugin.hpp"

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <linux/soundcard.h>
#include <boost/thread.hpp>



using namespace std;


class UserC_Output : public UserC_Plugin
{
public:
	UserC_Output();
	~UserC_Output();
	void start();
	void stop();
	void load_queues(CoreC_DQueue * front ,CoreC_DQueue * back);
private:
	CoreC_DQueue *_front;
	CoreC_DQueue *_back;
	bool _running;

};

#endif


UserC_Output::UserC_Output()
{
	_running = false;
}

void UserC_Output::start()
{
	_running = true;
	CoreC_Data * pcm = NULL;
	CoreC_Settings * set = CoreC_Settings::Instance();
	int n;
	int fd;
	int status;
	int arg;
	int bitrate;
	int channels;
	int depth;

	fd = open("/dev/dsp", O_RDWR);
	if (fd < 0) {
		utill_log(std::string(__FILE__) + ": could not open the dsp");
		return;
	}
	while(!set->isSet("stream.bitrate"))
	{
		boost::this_thread::sleep(boost::posix_time::milliseconds(5));
	}
	bitrate = utill_to_int(set->getSetting("stream.bitrate"));

	while(!set->isSet("stream.depth"))
	{
		boost::this_thread::sleep(boost::posix_time::milliseconds(5));
	}
	depth = utill_to_int(set->getSetting("stream.depth"));

	while(!set->isSet("stream.channels"))
	{
		boost::this_thread::sleep(boost::posix_time::milliseconds(5));
	}
	channels = utill_to_int(set->getSetting("stream.channels"));

	utill_log(std::string(__FILE__) + ": Starting PCM output Channels: " + utill_to_string(channels) + " Depth: " + utill_to_string(depth) + " Rate:" +utill_to_string(bitrate));

	arg = depth;
	status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
	if (status == -1)
	{
		utill_log(std::string(__FILE__) + ": SOUND_PCM_WRITE_BITS ioctl failed");
		close(fd);
		return;
	}
	if (arg != depth)
	{
		utill_log(std::string(__FILE__) + ": Unable to set sample depth");
		close(fd);
		return;
	}
	arg = channels;
	status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
	if (status == -1)
	{
		utill_log(std::string(__FILE__) + ": SOUND_PCM_WRITE_CHANNELS ioctl failed");
		close(fd);
		return;
	}
	if (arg != channels)
	{
		close(fd);
		return;
	}
	arg = bitrate;
	status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
	if (status == -1)
	{
		utill_log(std::string(__FILE__) + ": SOUND_PCM_WRITE_WRITE ioctl failed");
		close(fd);
		return;
	}
	while(_running)
	{
		pcm = _front->pop();
		write(fd, pcm->get_data(), pcm->get_header()->_size);
		delete pcm;
	}
}

void UserC_Output::stop()
{
	_running = false;

}

void UserC_Output::load_queues(CoreC_DQueue* front ,CoreC_DQueue* back)
{
	_front  = front;
	_back  = back;
}


extern "C"
{
	UserC_Plugin* Core_GetInstance()
	{
		return new UserC_Output();
	}

	void Core_KillInstance(UserC_Plugin* a)
	{
		delete a;
	}
}
